package com.jaka.framework.core.dingding.config;

import com.jaka.framework.core.dingding.api.DingTalkAPIClient;
import okhttp3.OkHttpClient;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.cert.CertificateException;
import java.util.concurrent.TimeUnit;

/**
 * @author ：james.liu
 * @date ：Created in 2021/12/14 15:37
 * @description：接口配置类
 * @version: 1.0
 */
public abstract class APIClientConfiguration {

    /**
     * 客户端使用相关配置直接配置相关参数
     */
    protected void setClientConfiguration() {
    }

    /**
     * 描述：API测试环境url
     */
    protected static final String apiTestUrl = "";

    /**
     * 描述：API生产环境url
     */
    protected static final String apiProductUrl = "https://oapi.dingtalk.com/";

    /**
     * 描述：连接超时时间（默认：15s）
     */
    protected int connectTimeout = 15000;
    /**
     * 描述：读取数据超时时间（默认：5s）
     */
    protected int readTimeout = 5000;
    /**
     * 描述：写入数据超时时间（默认：5s）
     */
    protected int writeTimeout = 5000;

    /**
     * 描述：是否开启 测试环境模式<br/>
     * 默认为 false，指向生产环境<br/>
     * 生产环境：${apiProductUrl}<br/>
     * 测试环境：${apiTestUrl}<br/>
     */
    protected boolean enableTestMode = false;
    /**
     * 描述：API接口请求地址<br/>
     * 生产环境：${apiProductUrl}<br/>
     * 测试环境：${apiTestUrl}<br/>
     */
    protected transient String apiUrl = apiProductUrl;
    /**
     * 这里需配置你的钉钉Key
     */
    protected String accessKey = "";
    /**
     *
     */
    protected String accessSecret = "";

    /**
     *
     */
    protected String accessToken;

    /**
     * 描述：全局的http请求工具
     */
    protected volatile OkHttpClient okHttpClient = null;

    /**
     * 描述：构建一个API客户端
     */
    public abstract DingTalkAPIClient build();

    /**
     * 描述：连接超时时间（默认：15s）（获取）
     */
    public int getConnectTimeout() {
        return connectTimeout;
    }

    /**
     * 描述：连接超时时间（默认：15s）（设置）
     */
    public APIClientConfiguration setConnectTimeout(int connectTimeout) {
        this.connectTimeout = connectTimeout;
        return this;
    }

    /**
     * 描述：读取数据超时时间（默认：5s）（获取）
     */
    public int getReadTimeout() {
        return readTimeout;
    }

    /**
     * 描述：读取数据超时时间（默认：5s）（设置）
     */
    public APIClientConfiguration setReadTimeout(int readTimeout) {
        this.readTimeout = readTimeout;
        return this;
    }

    /**
     * 描述：写入数据超时时间（默认：5s）（获取）
     */
    public int getWriteTimeout() {
        return writeTimeout;
    }

    /**
     * 描述：写入数据超时时间（默认：5s）（设置）
     */
    public APIClientConfiguration setWriteTimeout(int writeTimeout) {
        this.writeTimeout = writeTimeout;
        return this;
    }

    /**
     * 描述：是否开启 测试环境模式<br/>
     * 默认为 false，指向生产环境<br/>
     * 生产环境：${apiProductUrl}<br/>
     * 测试环境：${apiTestUrl}<br/>
     */
    public boolean isEnableTestMode() {
        return enableTestMode;
    }

    /**
     * 描述：是否开启 测试环境模式<br/>
     * 默认为 false，指向生产环境<br/>
     * 生产环境：${apiProductUrl}<br/>
     * 测试环境：${apiTestUrl}<br/>
     */
    public APIClientConfiguration setEnableTestMode(boolean enableTestMode) {
        this.enableTestMode = enableTestMode;
        return this;
    }

    /**
     * 描述：API接口请求地址<br/>
     * 生产环境：${apiProductUrl}<br/>
     * 测试环境：${apiTestUrl}<br/>
     */
    public String getApiUrl() {
        return apiUrl;
    }

    /**
     * 描述：API接口请求地址<br/>
     * 生产环境：${apiProductUrl}<br/>
     * 测试环境：${apiTestUrl}<br/>
     */
    public APIClientConfiguration setApiUrl(String apiUrl) {
        this.apiUrl = apiUrl;
        return this;
    }

    /**
     * 描述：获取访问秘钥。
     */
    public String getAccessKey() {
        return accessKey;
    }

    /**
     * 描述：设置访问秘钥。
     */
    public APIClientConfiguration setAccessKey(String accessKey) {
        this.accessKey = accessKey;
        return this;
    }

    public String getAccessSecret() {
        return accessSecret;
    }

    public APIClientConfiguration setAccessSecret(String accessSecret) {
        this.accessSecret = accessSecret;
        return this;
    }

    /**
     * 描述：全局的http请求工具（获取）
     */
    public OkHttpClient getOkHttpClient() {
        return okHttpClient;
    }

    /**
     * 描述：全局的http请求工具（设置）
     */
    public APIClientConfiguration setOkHttpClient(OkHttpClient okHttpClient) {
        this.okHttpClient = okHttpClient;
        return this;
    }

    public String getAccessToken() {
        return accessToken;
    }

    public APIClientConfiguration setAccessToken(String accessToken) {
        this.accessToken = accessToken;
        return this;
    }

    /**
     * 描述：当 OkHttpClient 为NULL 是时候 自动根据当前配置  设置全局的http请求工具（设置）
     */
    public synchronized void autoSetOkHttpClientIfOkHttpClientIsNull() {
        if (this.okHttpClient == null) {
            try {
                final TrustManager[] trustAllCerts = new TrustManager[]{
                        new X509TrustManager() {
                            @Override
                            public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                            }

                            @Override
                            public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                            }

                            @Override
                            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                                return new java.security.cert.X509Certificate[]{};
                            }
                        }
                };

                // Install the all-trusting trust manager
                final SSLContext sslContext = SSLContext.getInstance("SSL");
                sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
                // Create an ssl socket factory with our all-trusting manager
                final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

                this.okHttpClient = new OkHttpClient.Builder().
                        connectTimeout(connectTimeout, TimeUnit.MILLISECONDS).
                        readTimeout(readTimeout, TimeUnit.MILLISECONDS).
                        writeTimeout(writeTimeout, TimeUnit.MILLISECONDS).
                        build();

            } catch (Exception e) {
                ///
            }

        }


    }
}